package com.sys.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sys.entity.SysFile;
import com.sys.service.SysFileService;
import com.sys.utils.Utils;
import com.bhudy.base.QueryFilter;
import com.bhudy.enums.Relation;
import com.bhudy.exception.SysException;
import com.bhudy.exception.SysExceptionCode;
import com.bhudy.utils.ResponseResult;
import com.bhudy.utils.XqhUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author 卞洪业
 * @Description 文件上传controller
 * @Date 2019-10-30 23:09:37
 */
@RestController
public class SysFileController {
    @Autowired
    private SysFileService sysFileService;

    /**
     * 获取sysFile表的数据
     *
     * @param page  页数{1}
     * @param limit 显示数量{10}
     * @return sysFile的list
     */
    @GetMapping(value = "/api/v1/sysFiles")
    public ResponseResult getAll(Integer page, Integer limit, String fileName, String fileContentType, Long objId) {
        QueryFilter queryFilter = new QueryFilter().and("status", Relation.NOT_EQUAL, 1);
        if (page != null && limit != null) queryFilter.limit(--page, limit);
        if (fileName != null && !fileName.equals("")) {
            queryFilter.andLike("fileName", "%" + fileName + "%");
        }
        if (fileContentType != null && !fileContentType.equals("")) {
            queryFilter.andLike("fileContentType", "%" + fileContentType + "%");
        }
        if (objId != null) {
            queryFilter.and("objId", objId);
        }
        return ResponseResult.printMapJson(0, sysFileService.count(queryFilter), sysFileService.findList(queryFilter));
    }

    @GetMapping(value = "/api/v1/sysFile")
    public ResponseResult get(Long fileId) {
        return ResponseResult.printMapJson(0, sysFileService.get(fileId));
    }

    @PostMapping(value = "/api/v1/sysFile")
    public ResponseResult insert(@RequestBody String json) {
        return ResponseResult.printMapJson(0, sysFileService.insert(JSONObject.parseObject(json, SysFile.class)));
    }

    @PutMapping(value = "/api/v1/sysFile")
    public ResponseResult update(@RequestBody String json) {
        return ResponseResult.printMapJson(0, sysFileService.update(JSONObject.parseObject(json, SysFile.class)));
    }

    @DeleteMapping(value = "/api/v1/sysFiles")
    public ResponseResult delete(@RequestBody String json) {
        try {
            QueryFilter queryFilter = new QueryFilter();
            queryFilter.and("fileId", Relation.IN, JSONObject.parseObject(json, String[].class));
            List<SysFile> sysFileList = sysFileService.findList(queryFilter);

            File path = new File(ResourceUtils.getURL("classpath:").getPath() + File.separator + "static" + File.separator);
            if (Utils.isBlank(sysFileList)) {
                for (SysFile sysFile : sysFileList) {
                    File fPath = new File(path.getAbsolutePath(), sysFile.getFilePath());
                    if (fPath.exists()) {
                        fPath.delete();
                    }
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return ResponseResult.printMapJson(0, sysFileService.delete(JSONObject.parseObject(json, String[].class)));
    }

    /**
     * 文件上传接口
     *
     * @param file MultipartFile文件
     * @return 处理的状态
     */
    @RequestMapping(value = "/api/v1/sysUpload", method = RequestMethod.POST)
    public Object upload(@RequestParam(value = "file", required = false) MultipartFile file, Long objId, String objType) {
        try {
            if (file == null) throw new SysException(SysExceptionCode.CODE_40002);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            //获取跟目录
            File path = new File(ResourceUtils.getURL("classpath:").getPath() + File.separator + "static" + File.separator);

            if (!path.exists()) path.mkdirs();
            Long uuid = XqhUtils.createId();
            String prefix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
            //src\main\resources
            String pathFull = File.separator + "res" + File.separator + "upload" + File.separator + sdf.format(new Date()) + File.separator;
            //如果上传目录为/static/res/upload/，则可以如下获取：
            File fPath = new File(path.getAbsolutePath(), pathFull);
            if (!fPath.exists()) {
                fPath.mkdirs();
            }
            File newFile = new File(fPath.getAbsolutePath(), uuid + "." + prefix);
            //通过CommonsMultipartFile的方法直接写文件（注意这个时候）
            file.transferTo(newFile);

            Map<String, Object> fileMetaMap = new HashMap<>();
            fileMetaMap.put("canRead", newFile.canRead()); // 文件是否可读
            fileMetaMap.put("canWrite", newFile.canWrite()); // 文件是否可写
            fileMetaMap.put("canExecute", newFile.canExecute()); // 文件是否可执行
            fileMetaMap.put("length", newFile.length()); // 获取文件字节数
            fileMetaMap.put("name", newFile.getName()); // 获取文件名
            fileMetaMap.put("lastModified", newFile.lastModified()); // 获取最后一次修改日期时间
            fileMetaMap.put("isHidden", newFile.isHidden()); // 判断是否是隐藏文件
            fileMetaMap.put("isDirectory", newFile.isDirectory()); // 判断是否是目录
            fileMetaMap.put("isFile", newFile.isFile()); // 判断是否是文件
            fileMetaMap.put("prefix", prefix); // 获取文件后缀名
            fileMetaMap.put("contentType", file.getContentType()); // 获取文件contentType

            SysFile sysFile = new SysFile();
            sysFile.setFileId(uuid);
            sysFile.setFileMd5(Utils.getFileMD5(newFile));
            sysFile.setFileName(file.getOriginalFilename());
            sysFile.setFilePath(pathFull + uuid + "." + prefix);
            sysFile.setFileSize(file.getSize());
            sysFile.setFileExtension(prefix);
            sysFile.setFileMeta(JSON.toJSONString(fileMetaMap));
            sysFile.setFileContentType(file.getContentType());
            sysFile.setObjId(objId);
            sysFile.setObjType(objType);

            sysFileService.insert(sysFile);

            return ResponseResult.printMapJson(0, sysFile);
        } catch (IOException e) {
            throw new SysException(SysExceptionCode.CODE_40027);
        }
    }

    /**
     * 文件下载接口
     *
     * @param id       sysFile表的Id
     * @param response HttpServletResponse
     */
    @RequestMapping(value = "/api/v1/sysDownload", method = RequestMethod.GET)
    public void download(String id, HttpServletResponse response) {
        FileInputStream input = null;
        try {
            SysFile sysFile = sysFileService.get(id);
            if (sysFile == null) throw new SysException(SysExceptionCode.CODE_40002);

            OutputStream os;
            File path = new File(ResourceUtils.getURL("classpath:").getPath() + File.separator + "static" + File.separator);
            if (!path.exists()) path.mkdirs(); // path = new File("");

            File f = new File(path.getAbsolutePath(), sysFile.getFilePath());
            input = new FileInputStream(f);
            byte[] buffer = new byte[(int) f.length()];
            int offset = 0;
            int numRead = 0;
            while (offset < buffer.length && (numRead - input.read(buffer, offset, buffer.length - offset)) >= 0) {
                offset += numRead;
            }


            os = response.getOutputStream();
            response.setContentType("application/force-download;charset=ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(sysFile.getFileName().getBytes(), "ISO8859-1"));
            os.write(buffer);
        } catch (IOException e) {
            throw new SysException(SysExceptionCode.CODE_40027);
        } finally {
            try {
                if (input != null) input.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
